/*
 * Copyright 2008-2023 dexian.vip. All rights reserved.
 * Support: http://www.dexian.vip
 * License: http://www.dexian.vip/license
 */

package vip.dexian.admin.security.dynamic;

import cn.hutool.core.text.CharSequenceUtil;
import vip.dexian.common.CommonAttributes;
import jakarta.annotation.PostConstruct;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.util.ArrayList;
import java.util.List;

/**
 * 权限配置文件
 *
 * @author 挺好的 2023年06月06日 8:53
 */
@ConfigurationProperties ("authorization")
@Component ("authorizationProperties")
public class AuthorizationProperties {

    /**
     * 标准权限
     */
    protected static final String[] STANDARD_PERMS = new String[] {"list", "save", "update", "delete"};

    /**
     * controller request mapping 前缀
     */
    public static final String CONTROLLER_REQUEST_MAPPING_PREFIX = "/admin/";

    /**
     * 授权的权限
     */
    private List <AuthorizationItem> list;

    /**
     * 处理好的权限...
     */
    private List <AuthorizationItem> authorizes;

    private final PathMatcher pathMatcher = new AntPathMatcher();

    /**
     * 根据请求获取授权的配置项目
     *
     * @param requestURI
     *         请求路径
     *
     * @return 如果requestURI is empty 或者 不存在，返回false
     */
    public AuthorizationItem getItemByRequestURI (String requestURI) {

        if (StringUtils.isEmpty(requestURI)) {
            return null;
        }

        return this.authorizes.stream()
                .filter(authorizationItem -> AuthorizationProperties.this.pathMatcher.match(authorizationItem.getUrl(),
                        requestURI
                )).findAny().orElse(null);
    }


    @PostConstruct
    public void init () {
        // 初始化权限list
        this.authorizes = new ArrayList <>();

        for (AuthorizationItem item : this.list) {

            List <String> values = item.getValues();

            // 如果为null，表示是单独的权限标识
            if (values == null) {
                // 获取名称
                String name = item.getName();
                String url = this.generateUrl(item);
                this.authorizes.add(this.generateItem(name, url));
            } else {
                this.add(item);
            }
        }
    }

    public void setList (List <AuthorizationItem> list) {
        this.list = list;
    }

    public List <AuthorizationItem> getAuthorizes () {
        return this.authorizes;
    }

    public void setAuthorizes (List <AuthorizationItem> authorizes) {
        this.authorizes = authorizes;
    }

    /**
     * 转换并添加权限
     *
     * @param item
     *         授权条目
     */
    private void add (AuthorizationItem item) {

        List <String> values = item.getValues();
        String name = item.getName();
        // 转换为带下划线
        String underlineName = CharSequenceUtil.toUnderlineCase(name);
        // 没有数据
        if (values.isEmpty()) {
            for (String value : STANDARD_PERMS) {
                this.add(name, underlineName, value);
            }

        } else {
            for (String value : values) {
                this.add(name, underlineName, value);
            }
        }
    }

    private void add (String name, String underlineName, String value) {
        String permName = name + ":" + value;
        String url = CONTROLLER_REQUEST_MAPPING_PREFIX + underlineName + CommonAttributes.PATH_SEPARATOR + value;
        this.authorizes.add(this.generateItem(permName, url));
    }

    /**
     * 生成item
     *
     * @param name
     *         权限标识
     * @param url
     *         权限路径
     *
     * @return {@link AuthorizationItem}
     */
    private AuthorizationItem generateItem (String name, String url) {
        AuthorizationItem item = new AuthorizationItem();
        item.setName(name);
        item.setUrl(url);
        return item;
    }

    /**
     * 如果配置了url,则直接返回url，否则，返回驼峰转下划线之后的url
     *
     * @param item
     *         item
     *
     * @return url
     */
    private String generateUrl (AuthorizationItem item) {

        String url = item.getUrl();

        if (StringUtils.isNotEmpty(url)) {
            return url;
        }

        String underlineName = CharSequenceUtil.toUnderlineCase(item.getName());

        return CONTROLLER_REQUEST_MAPPING_PREFIX + StringUtils.replace(underlineName, ":",
                CommonAttributes.PATH_SEPARATOR
        );
    }


}
